package com.zoweunion.mechanic.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

public class FunUtil {

    public static final Logger logger = LoggerFactory.getLogger(FunUtil.class);


    /**
     * date2比date1多的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int betweenDaysCount(Date date1, Date date2) {

        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2) {//同一年
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)    //闰年
                {
                    timeDistance += 366;
                } else    //不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2 - day1);
        } else {// 不同年
            System.out.println("判断day2 - day1 : " + (day2 - day1));
            return day2 - day1;
        }
    }

    /**
     * date2比date1多的天数,一般如果计算该时间天数的话，还需要在返回的值上+1
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int betweenDaysCount(String startDate, String endDate) {

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd ");

        Date date1 = null;
        try {
            date1 = formatter.parse(startDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Date date2 = null;
        try {
            date2 = formatter.parse(endDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2) {//同一年
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)    //闰年
                {
                    timeDistance += 366;
                } else    //不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2 - day1);
        } else {// 不同年
            System.out.println("判断day2 - day1 : " + (day2 - day1));
            return day2 - day1;
        }
    }


    /**
     * 返回两个日期之间的所有日期列表
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> getEveryDayList(Date startDate, Date endDate) {
        List<String> ls = new ArrayList<>();
        int days = betweenDaysCount(startDate, endDate);

        for (int i = 0; i <= days; i++) {

            Calendar cal = Calendar.getInstance();
            cal.setTime(startDate);
            cal.add(Calendar.DATE, i);
            Date time = cal.getTime();
            SimpleDateFormat localFormater = new SimpleDateFormat("yyyy-MM-dd");
            String localTime = localFormater.format(time);
            ls.add(localTime);
        }

        return ls;
    }


    /**
     * 获取两个日期之间的所有月份 (年月)
     *
     * @param startTime
     * @param endTime
     * @return：list
     */
    public static List<String> getEveryMonthList(String startTime, String endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        // 声明保存日期集合
        List<String> list = new ArrayList<>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {

                // 把日期添加到集合
                list.add(sdf.format(startDate));

                // 设置日期
                calendar.setTime(startDate);

                //把月数增加 1
                calendar.add(Calendar.MONTH, 1);

                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 获取两个日期之间的所有月份 (年月)
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> getEveryMonthList(Date startDate, Date endDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        // 声明保存日期集合
        List<String> list = new ArrayList<>();
        try {
            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {

                // 把日期添加到集合
                list.add(sdf.format(startDate));

                // 设置日期
                calendar.setTime(startDate);

                //把月数增加 1
                calendar.add(Calendar.MONTH, 1);

                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 把前端传过来的[1,2,3]转换成字符串 1,2,3
     *
     * @param jsonArray
     * @param delimiter
     * @return
     */
    public static String implode(JSONArray jsonArray, String delimiter) {

        // 把前端传过来的[1,2,3]转换成字符串 1,2,3
        //创建一个与JSONArray 长度相同的String数组
        String[] strings = new String[jsonArray.size()];
        //使用JSONArray 中的toArray进行转换
        String[] strings1 = jsonArray.toArray(strings);
        //使用java流将数组中的字符串进行拼接
        String string2 = Arrays.stream(strings1).collect(Collectors.joining(delimiter));

        return string2;
    }

    /**
     * 获取map中最大值的key
     *
     * @param map
     * @return
     */
    public static String getMapKeyWithMaxValue(Map<String, Object> map) {
        int maxV = 0;
        String maxK;
        //临时值，保存每次最大值键，下个值比他大就将他替掉，换成新值
        String maxKRemove = null;
        Map<String, Object> map2 = new TreeMap();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            maxK = entry.getKey();
            int value = Integer.parseInt(entry.getValue().toString());
            if (value > maxV) {
                if (null != maxKRemove) {
                    map2.clear();
                }
                maxV = value;
                map2.put(maxK, maxV);
                maxKRemove = maxK;
            } else if (value == maxV) {
                map2.put(maxK, maxV);
            }
        }

        String strKey = "";
        int value = 0;
        for (Map.Entry<String, Object> entry : map2.entrySet()) {
            maxK = entry.getKey();
            value = Integer.parseInt(entry.getValue().toString());
            String[] maxKey = maxK.split("_");
            strKey = maxKey[0];
        }
        System.out.println("Key：" + strKey + "，Value：" + value);
        return strKey;
    }

    /**
     * 获取map中最小值的key
     *
     * @param map
     * @return
     */
    public static String getMapKeyWithMinValue(Map<String, Object> map) {
        int minValue = Integer.MAX_VALUE;
        String minKey = null;

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (Integer.parseInt(entry.getValue().toString()) < minValue) {
                minValue = Integer.parseInt(entry.getValue().toString());
                minKey = entry.getKey();
            }
        }

        return minKey;
    }


    /**
     * 获取map中最大值的所有key数组
     *
     * @param map
     * @return
     */
    public static String[] getMapKeysWithMaxValue(Map<String, Object> map) {
        int maxV = Integer.MIN_VALUE;
        Map<String, Integer> maxKeys = new HashMap<>();

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            int value = Integer.parseInt(entry.getValue().toString());
            if (value > maxV) {
                maxKeys.clear();
                maxV = value;
                maxKeys.put(entry.getKey(), maxV);
            } else if (value == maxV) {
                maxKeys.put(entry.getKey(), maxV);
            }
        }

        String[] strKeys = maxKeys.keySet().toArray(new String[0]);
        return strKeys;
    }


    /**
     * 获取map中最小值的所有key数组
     *
     * @param map
     * @return
     */
    public static String[] getMapKeysWithMinValue(Map<String, Object> map) {

        List<String> keys = new ArrayList<>();
        Object minValue = Collections.min(map.values(), new Comparator<Object>() {
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Comparable && o2 instanceof Comparable) {
                    return ((Comparable) o1).compareTo((Comparable) o2);
                } else {
                    return o1.toString().compareTo(o2.toString());
                }
            }
        });
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue().equals(minValue)) {
                keys.add(entry.getKey());
            }
        }
        String[] keysArray = keys.toArray(new String[0]);
        return keysArray;
    }

    /**
     * 根据经纬度，计算两点间的距离
     *
     * @param longitudeFrom 第一个点的经度
     * @param latitudeFrom  第一个点的纬度
     * @param longitudeTo   第二个点的经度
     * @param latitudeTo    第二个点的纬度
     * @return double 返回距离 单位米
     */
    public static double getDistance(double longitudeFrom, double latitudeFrom, double longitudeTo, double latitudeTo) {
        GlobalCoordinates source = new GlobalCoordinates(latitudeFrom, longitudeFrom);
        GlobalCoordinates target = new GlobalCoordinates(latitudeTo, longitudeTo);
        return new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.Sphere, source, target).getEllipsoidalDistance();
    }

    /**
     * 实体类列表转换成 map列表
     * List<Entity> 转化成 List<Map<String,Object>>
     * @return
     */
    public static <T> List<Map<String, Object>> objectListToMapList(List<T> objectList) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (T obj : objectList) {
            String json = JSONObject.toJSONString(obj);
            Map<String, Object> map = JSONObject.parseObject(json, Map.class);
            mapList.add(map);
        }
        return mapList;
    }

    /**
     * 将 Entity 转化为 Vo
     * @param source
     * @param target
     * @param <T>
     * @return
     */
    public static <T> T entityToVo(Object source, Class<T> target) {
        if (source == null) {
            return null;
        }
        T targetObject = null;
        try {
            targetObject = target.newInstance();
            BeanUtils.copyProperties(source, targetObject);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return targetObject;
    }

    /**
     * 将 List<Entity> 转换为List<Vo>
     * @param sourceList
     * @param target
     * @param <T>
     * @return
     */
    public static <T> List<T> entityToVoList(Collection<?> sourceList, Class<T> target) {
        if (sourceList == null) {
            return null;
        }
        List<T> targetList = new ArrayList<>(sourceList.size());
        try {
            for (Object source : sourceList) {
                T targetObject = target.newInstance();
                BeanUtils.copyProperties(source, targetObject);
                targetList.add(targetObject);
            }
        } catch (Exception e) {
            logger.error("convert error ", e);
        }
        return targetList;
    }



}
